﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using GraphAPI;
using System.IO;
using GraphAPI.Model;

namespace GraphEditor
{
	public partial class EditorForm : Form
	{
		public EditorForm()
		{
			InitializeComponent();
		}

		private void closeToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void toolStripButton1_Click(object sender, EventArgs e)
		{
			this.toolStripButton1.Checked = true;
			this.toolStripButton2.Checked = false;
			this.toolStripButton3.Checked = false;
			this.toolStripButton4.Checked = false;

			this.редактироватьToolStripMenuItem.Checked = true;
			this.добавитьВершинуToolStripMenuItem.Checked = false;
			this.создатьСвязьToolStripMenuItem.Checked = false;
			this.создатьОриентированнуюСвязьToolStripMenuItem.Checked = false;
			
			graphPanel.State = GraphPanel.CursorState.Pointer;
		}

		private void toolStripButton2_Click(object sender, EventArgs e)
		{
			this.toolStripButton1.Checked = false;
			this.toolStripButton2.Checked = true;
			this.toolStripButton3.Checked = false;
			this.toolStripButton4.Checked = false;

			this.редактироватьToolStripMenuItem.Checked = false;
			this.добавитьВершинуToolStripMenuItem.Checked = true;
			this.создатьСвязьToolStripMenuItem.Checked = false;
			this.создатьОриентированнуюСвязьToolStripMenuItem.Checked = false;

			graphPanel.State = GraphPanel.CursorState.Node;
		}

		private void toolStripButton3_Click(object sender, EventArgs e)
		{
			this.toolStripButton1.Checked = false;
			this.toolStripButton2.Checked = false;
			this.toolStripButton3.Checked = true;
			this.toolStripButton4.Checked = false;

			this.редактироватьToolStripMenuItem.Checked = false;
			this.добавитьВершинуToolStripMenuItem.Checked = false;
			this.создатьСвязьToolStripMenuItem.Checked = true;
			this.создатьОриентированнуюСвязьToolStripMenuItem.Checked = false;

			graphPanel.State = GraphPanel.CursorState.Connection;
		}

		private void toolStripButton4_Click(object sender, EventArgs e)
		{
			this.toolStripButton1.Checked = false;
			this.toolStripButton2.Checked = false;
			this.toolStripButton3.Checked = false;
			this.toolStripButton4.Checked = true;

			this.редактироватьToolStripMenuItem.Checked = false;
			this.добавитьВершинуToolStripMenuItem.Checked = false;
			this.создатьСвязьToolStripMenuItem.Checked = false;
			this.создатьОриентированнуюСвязьToolStripMenuItem.Checked = true;

			graphPanel.State = GraphPanel.CursorState.OrientedConnection;
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			Algorithm[] algorithms = AlgorithmManager.Instance.Algorithms;

			алгоритмыToolStripMenuItem.DropDownItems.Clear();

			foreach (Algorithm algorithm in algorithms)
			{
				ToolStripMenuItem parent = алгоритмыToolStripMenuItem;

				if (algorithm.AlgorithmObject.Category != null && algorithm.AlgorithmObject.Category.Length > 0)
				{
					ToolStripItem[] foundItems = алгоритмыToolStripMenuItem.DropDownItems.Find(algorithm.AlgorithmObject.Category, true);
					if (foundItems.Length == 0)
					{
						ToolStripMenuItem category = new ToolStripMenuItem(algorithm.AlgorithmObject.Category);
						category.Name = algorithm.AlgorithmObject.Category;
						алгоритмыToolStripMenuItem.DropDownItems.Add(category);
						parent = category;
					}
					else
					{
						ToolStripMenuItem category = foundItems[0] as ToolStripMenuItem;
						if (category != null)
							parent = category;
					}
				}
				
				ToolStripMenuItem menuItem = new ToolStripMenuItem(algorithm.AlgorithmObject.Name);
				menuItem.Tag = algorithm;
				menuItem.Click += new EventHandler(menuItem_Click);
				parent.DropDownItems.Add(menuItem);
			}
		}

		void menuItem_Click(object sender, EventArgs e)
		{
			Algorithm alg;
			if (sender is ToolStripMenuItem)
			{
				alg = (sender as ToolStripMenuItem).Tag as Algorithm;
			}
			else if (sender is ToolStripDropDownItem)
			{
				alg = (sender as ToolStripDropDownItem).Tag as Algorithm;
			}
			else
			{
				return;
			}

			IAlgorithm algorithm = alg.AlgorithmObject;

			Control c = algorithm.Use(new Graph(graphPanel.Graph));
			AlgorithmForm form = new AlgorithmForm(c, algorithm.Name);

			if (this.WindowState == FormWindowState.Maximized)
				form.WindowState = FormWindowState.Maximized;
			else
				form.ClientSize = this.ClientSize;

			form.Show();
		}

		private void редактироватьToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.toolStripButton1_Click(sender, e);
		}

		private void graphPanel_Load(object sender, EventArgs e)
		{

		}

		private void добавитьВершинуToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.toolStripButton2_Click(sender, e);
		}

		private void создатьСвязьToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.toolStripButton3_Click(sender, e);
		}

		private void создатьОриентированнуюСвязьToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.toolStripButton4_Click(sender, e);
		}

		private void graphPropertiesToolStripMenuItem_Click(object sender, EventArgs e)
		{
			PropertiesForm frm = new PropertiesForm(graphPanel);
			frm.Show();
			
		}

		private void PropertiesForm(GraphAPI.Model.Graph graph)
		{
			
		}

		private void слегкаПомочьToolStripMenuItem_Click(object sender, EventArgs e)
		{
			AboutForm form = new AboutForm();
			form.ShowDialog();
		}

        private void toolStripButton5_Click(object sender, EventArgs e)
        {

        }

        private void toolStripButton5_Click_1(object sender, EventArgs e)
        {
            graphPropertiesToolStripMenuItem_Click(sender, e);
        }

        private void размерВершинToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void диаметрГрафаToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void центрГрафаToolStripMenuItem_Click(object sender, EventArgs e)
        {
		}

		string fileName = "";

		private void saveToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (fileName.Length == 0)
			{
				сохранитьКагToolStripMenuItem_Click(sender, e);
				return;
			}

			FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write);
			GraphXmlSerializer.Serialize(graphPanel.Graph, file);
			file.Close();
		}

		private void сохранитьКагToolStripMenuItem_Click(object sender, EventArgs e)
		{
			saveFileDialog.Title = "Сохранение графа";
			saveFileDialog.Filter = "Файлы графов (*.graph)|*.graph";
			if (saveFileDialog.ShowDialog() != DialogResult.OK)
				return;

			fileName = saveFileDialog.FileName;
			this.Text = "GraphEditor - " + Path.GetFileName(fileName);
			saveToolStripMenuItem_Click(sender, e);
		}

		private void newToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (MessageBox.Show("Создать новый граф?", "Новый граф", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
			{
				graphPanel.Graph = new Graph();
				fileName = "";
				this.Text = "GraphEditor";

                toolStripButton1_Click(sender, e);
                graphPanel.vertexNameIndex = 1;
                graphPanel.relationNameIdex = 1;
			}
		}

		private void openToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (openFileDialog.ShowDialog() != DialogResult.OK)
				return;

			fileName = openFileDialog.FileName;
			this.Text = "GraphEditor - " + Path.GetFileName(fileName);

			FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read);
			graphPanel.Graph = GraphXmlSerializer.DeserializeGraph(file);

            graphPanel.vertexNameIndex = graphPanel.Graph.EntityCount;
            graphPanel.relationNameIdex = graphPanel.Graph.RelationCount;

			file.Close();
		}

		private void EditorForm_Activated(object sender, EventArgs e)
		{
			graphPanel.Focus();
		}

		private void graphPanel_KeyDown(object sender, KeyEventArgs e)
		{
		}

		private void EditorForm_KeyDown(object sender, KeyEventArgs e)
		{
			graphPanel_KeyDown(sender, e);
		}

		private void EditorForm_KeyUp(object sender, KeyEventArgs e)
		{
			graphPanel_KeyUp(sender, e);
		}

		private void graphPanel_KeyUp(object sender, KeyEventArgs e)
		{

		}

		private void неПомогатьToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Help.ShowHelpIndex(this, "help.chm");
		}

		private void btnHELP_Click(object sender, EventArgs e)
		{
			Help.ShowHelpIndex(this, "help.chm");
		}

		private void saveIndentsMatrixToolStripMenuItem_Click(object sender, EventArgs e)
		{
			saveFileDialog.Filter = "Текстовый файл (*.txt)|*.txt";
			saveFileDialog.Title = "Экспорт матрицы инцидентности";
			DialogResult res = saveFileDialog.ShowDialog(this);
			if (res == DialogResult.OK)
				ExportIndentsMatrix(saveFileDialog.FileName);
		}

		private void ExportIndentsMatrix(string path)
		{
			StreamWriter writer = new StreamWriter(path);
			writer.WriteLine("B(G) = ");

			for(int i = 0; i < graphPanel.Graph.EntityCount;i++)
			{
				for (int j = 0; j < graphPanel.Graph.RelationCount; j++)
				{
					writer.Write(graphPanel.Graph.IntendMatrix[i, j].ToString() + " ");
				}
				writer.WriteLine();
			}
			writer.Close();
		}
		private void ExportRelationMatrix(string path)
		{
			StreamWriter writer = new StreamWriter(path);
			writer.WriteLine("A(G) = ");

			for (int i = 0; i < graphPanel.Graph.EntityCount; i++)
			{
				for (int j = 0; j < graphPanel.Graph.EntityCount; j++)
				{
					writer.Write((graphPanel.Graph.RelationMatrix[i, j] ? "1" : "0") + " ");
				}
				writer.WriteLine();
			}
			writer.Close();
		}

		private void saveRelationMatrixBtn_Click(object sender, EventArgs e)
		{
			saveFileDialog.Filter = "Текстовый файл (*.txt)|*.txt";
			saveFileDialog.Title = "Экспорт матрицы смежности";
			DialogResult res = saveFileDialog.ShowDialog(this);

			if (res == DialogResult.OK)
				ExportRelationMatrix(saveFileDialog.FileName);
		}

		private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
		{
			e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

			Rectangle graphBounds = graphPanel.Graph.Bounds;

			float scaleX = (float)e.MarginBounds.Width / (float)graphBounds.Width;
			float scaleY = (float)e.MarginBounds.Height / (float)graphBounds.Height;
			float scale = (scaleX < scaleY) ? scaleX : scaleY;

			foreach (Relation rel in graphPanel.Graph.Relations)
			{
				float startX = ((float)rel.StartEntity.Position.X - (float)graphBounds.X) * scale + (float)e.MarginBounds.X;
				float startY = ((float)rel.StartEntity.Position.Y - (float)graphBounds.Y) * scale + (float)e.MarginBounds.Y;

				float endX = ((float)rel.EndEntity.Position.X - (float)graphBounds.X) * scale + (float)e.MarginBounds.X;
				float endY = ((float)rel.EndEntity.Position.Y - (float)graphBounds.Y) * scale + (float)e.MarginBounds.Y;

				e.Graphics.DrawLine(Pens.Black, startX, startY, endX, endY);

//				Font labelFont = new Font(this.Font, this.Font.Style);
				Font labelFont = new Font(this.Font.FontFamily.Name,
					this.Font.Size * scale,
					this.Font.Style);

				SizeF labelSize = e.Graphics.MeasureString(rel.Name, labelFont);

				PointF point = new PointF(
					(endX + startX) / 2 - labelSize.Width / 2,
					(endY + startY) / 2 - labelSize.Height / 2);

				e.Graphics.DrawString(rel.Name, labelFont, Brushes.Black, point);
			}

			foreach (Entity ent in graphPanel.Graph.Entitys)
			{
				float x = ((float)ent.Position.X - (float)graphBounds.X) * scale + (float)e.MarginBounds.X;
				float y = ((float)ent.Position.Y - (float)graphBounds.Y) * scale + (float)e.MarginBounds.Y;

				float rad = (float)ent.Radius * scale;

				RectangleF ellipseRect = new RectangleF(x - rad, y - rad, rad * 2, rad * 2);

				e.Graphics.FillEllipse(Brushes.LightGray, ellipseRect);
				e.Graphics.DrawEllipse(Pens.Black, ellipseRect);

				Font labelFont = new Font(this.Font.FontFamily.Name,
					this.Font.Size * scale,
					this.Font.Style);

				SizeF labelSize = e.Graphics.MeasureString(ent.Name, labelFont);

				PointF point = new PointF(x - labelSize.Width / 2, y - labelSize.Height / 2);
								
				e.Graphics.DrawString(ent.Name, labelFont, Brushes.Black, point);
			}
		}

		private void параметрыСтраницыToolStripMenuItem_Click(object sender, EventArgs e)
		{
			pageSetupDialog.ShowDialog();
		}

		private void печатьToolStripMenuItem_Click(object sender, EventArgs e)
		{
			printDialog.ShowDialog();
		}

		private void предпросмотрToolStripMenuItem_Click(object sender, EventArgs e)
		{
			printPreviewDialog.ShowDialog();
		}
	}
}
